#include <stdio.h>
#include <stdlib.h>
#include <opencv2/opencv.hpp>
#include <opencv/highgui.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

using namespace cv;

void error(const char *msg)
{
    perror(msg);
    exit(1);
}

char* itoa(int n) {
  // THIS CAUSES MEMORY LEAKS...
  string s = "";
  while(n>0) {
    s += (char)(n%10+'0');
    n/=10;
  }
  char* ans = new char[s.length()];
  for(int c=0;c<(int)s.length();c++) {
    ans[c] = s[s.length()-c-1];
  }
  return ans;
}

int main(int argc, char **argv)
{
  printf("Started\n");
  /* Make Connection */
  int sockfd, portno;
  sockaddr_in serv_addr;
  hostent *server;

  if (argc < 3) {
    fprintf(stderr,"usage %s hostname port\n", argv[0]);
    exit(0);
  }
  portno = atoi(argv[2]);
  sockfd = socket(AF_INET, SOCK_STREAM, 0);
  if (sockfd < 0) {
    error("ERROR opening socket");
  }
  server = gethostbyname(argv[1]);
  if (server == NULL) {
    fprintf(stderr,"ERROR, no such host\n");
    exit(0);
  }
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
  serv_addr.sin_port = htons(portno);
  if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) {
    error("ERROR connecting");
  }
  /* Done Connecting */
  printf("Finished Connecting\n");
  /* initialize camera */
  VideoCapture capture = VideoCapture(0);
  Mat frame;

  if(!capture.isOpened()) {
    fprintf( stderr, "Cannot open initialize webcam!\n");
    return 1;
  }

  clock_t start = clock();
  int frame_count = 0;
  
  while(true){
   /* get a frame */ 
   frame_count++;
   if(!capture.read(frame)) {
     continue;
   }
   
   //printf("frame dimensions: %i x %i\n",frame.rows,frame.cols);

   vector<uchar> buf;
   if(!imencode("*.jpg",frame,buf)) {
     break;
   }

   int size = (int)buf.size();
   write(sockfd,&size,sizeof(int)); // NOTE THAT THE 5 MAY NOT BE CORRECT...
   //write(sockfd,""+(char)0,1);

   char* message = new char[buf.size()];
   //printf("buf.size(): %i\n", (int)buf.size());
   for(int c=0;c<(int)buf.size();c++)
   {
     message[c] = (char)buf[c];
   }
   
   /*for(int c=0;c<(int)buf.size();c++)
   {
     printf("%i\n",buf[c]);
     }*/

   int bytes_sent = 0;
   while(bytes_sent < (int)buf.size()) {
     int increment = write(sockfd,message+bytes_sent,(int)buf.size()-bytes_sent);
     if(increment == -1) {
       continue;
     }
     bytes_sent += increment;
     //printf("bytes_sent: %i\n",bytes_sent);
   }
   delete []message;

   printf("\t%f\n", ((double)CLOCKS_PER_SEC*frame_count/((clock() - start))));
   fflush(stdout);

   //char* temp = new char;
    //read(sockfd,temp,1);
    //delete temp;
  }

  
  /* Close socket */
  close(sockfd);

  return 0;
}

